// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... namespace LargoCommon.Music { using System; using System.Diagnostics.Contracts; using System.Globalization; using System.Text; using System.Xml.Linq; using System.Xml.Serialization; using Abstract; using LargoCommon.Interfaces; using Midi; /// Musical tone. /// Tone is defined in given bit Range with a given Loudness. [Serializable] [XmlRoot] public sealed class MusicalPause : GeneralOwner, IMusicalTone { #region Fields and variables /// /// Bar Number To. /// private int barNumberTo; //// //// Bit Range. //// //// private BitRange bitRange; #endregion #region Constructors /// Initializes a new instance of the MusicalPause class. Serializable. public MusicalPause() { } /// Initializes a new instance of the MusicalPause class. /// Rhythmical range of bits. /// Number of musical bar. public MusicalPause( BitRange givenBitRange, int barNumber) { this.BitRange = givenBitRange; this.BarNumber = barNumber; this.ToneType = MusicalToneType.Empty; this.Loudness = MusicalLoudness.None; this.InstrumentNumber = (byte)MidiMelodicInstrument.None; } /// Initializes a new instance of the MusicalPause class. /// Rhythmical order. /// Musical duration. /// Number of musical bar. public MusicalPause( byte givenRhythmicOrder, byte givenDuration, int barNumber) { this.RhythmicOrder = givenRhythmicOrder; this.Duration = givenDuration; this.BarNumber = barNumber; this.ToneType = MusicalToneType.Empty; this.Loudness = MusicalLoudness.None; this.InstrumentNumber = (byte)MidiMelodicInstrument.None; } /// /// Initializes a new instance of the class. /// /// The xml element. /// The rhythmic order. public MusicalPause(XElement xelement, byte rorder) { Contract.Requires(xelement != null); this.BarNumber = XmlSupport.ReadIntegerAttribute(xelement.Attribute("Bar")); this.BitFrom = XmlSupport.ReadByteAttribute(xelement.Attribute("Start")); ////BitFrom this.Duration = XmlSupport.ReadByteAttribute(xelement.Attribute("Length")); var br = new BitRange(rorder, this.BitFrom, (byte)this.Duration); this.BitRange = br; this.ToneType = MusicalToneType.Empty; this.Loudness = MusicalLoudness.None; //// 2019/11 //// this.InstrumentNumber = (byte)MidiMelodicInstrument.None; var attrInstr = xelement.Attribute("Instrument"); if (attrInstr != null) { this.InstrumentNumber = XmlSupport.ReadByteAttribute(attrInstr); //// see lastInstrument ... } else { this.InstrumentNumber = (int)MidiMelodicInstrument.None; } } #endregion #region Properties - Xml /// /// Gets the get X element. /// /// /// Property description. /// public XElement GetXElement { get { var xe = new XElement( "Pause", new XAttribute("Bar", this.BarNumber), new XAttribute("Start", this.BitFrom), new XAttribute("Length", this.Duration)); return xe; } } #endregion #region Tone Properties /// Gets or sets type of musical tone. /// Property description. public MusicalToneType ToneType { get; set; } /// Gets or sets ordinal index of tone in musical track. /// Property description. public int OrdinalIndex { get; set; } /// Gets or sets loudness. /// Property description. public MusicalLoudness Loudness { get; set; } /// Gets or sets a value indicating whether property of musical tone. /// Property description. public bool IsReady { get; set; } /// Gets a value indicating whether IsPause. /// General musical property. /// Returns value. public bool IsPause => true; /// /// Gets a value indicating whether this instance is empty. /// /// /// true if this instance is empty; otherwise, false. /// public bool IsEmpty => true; /// Gets or sets bar number. /// Property description. public int BarNumber { get; set; } /// Gets or sets bar number. /// Property description. public int BarNumberTo { get => this.barNumberTo != 0 ? this.barNumberTo : this.BarNumber; set => this.barNumberTo = value; } /// Gets or sets staff number (MusicXml). /// Property description. public byte RhythmicOrder { get; set; } /// Gets or sets staff number (MusicXml). /// Property description. public int Duration { get; set; } /// Gets or sets staff number (MusicXml). /// Property description. public byte Staff { get; set; } /// Gets or sets voice number (MusicXml). /// Property description. public byte Voice { get; set; } /// /// Gets or sets a value indicating whether this instance is from previous bar. /// /// /// True if this instance is from previous bar; otherwise, false. /// public bool IsFromPreviousBar { get; set; } /// /// Gets or sets a value indicating whether [continue to next bar]. /// /// /// True if [continue to next bar]; otherwise, false. /// public bool IsGoingToNextBar { get; set; } /// Gets property of musical tone. /// Property description. public int BitPosition => ((this.BarNumber - 1) * this.RhythmicOrder) + this.BitFrom; /// Gets or sets BitFrom. /// Property description. public byte BitFrom { get; set; } /// Gets BitTo. /// Property description. public byte BitTo { get { var br = this.BitRange; return br?.BitTo ?? 0; } } /// Gets or sets index to harmonic structure. /// Musical instrument. /// /// Property description. public byte InstrumentNumber { get; set; } /// Gets or sets index to harmonic structure. /// Property description. public MidiChannel Channel { get; set; } /// /// Gets or sets the bit range. /// /// /// The bit range. /// public BitRange BitRange { get { Contract.Ensures(Contract.Result() != null); var bitRange = new BitRange(this.RhythmicOrder, this.BitFrom, (byte)this.Duration); return bitRange; } set { var bitRange = value; if (bitRange == null) { return; } this.RhythmicOrder = bitRange.Order; this.BitFrom = bitRange.BitFrom; this.Duration = bitRange.Length; } } #endregion #region Note Properties /// /// Gets or sets the length of the note. /// /// /// The length of the note. /// public NoteLength NoteLength { get; set; } #endregion #region Other Properties /// /// Gets the melodic identifier. /// /// /// The melodic identifier. /// public string MelodicIdentifier => $"Pause#{this.BitFrom}/{this.Duration}"; /// /// Gets the rhythmic identifier. /// /// /// The rhythmic identifier. /// public string RhythmicIdentifier => $"{this.BitFrom}/{this.Duration}"; #endregion #region Static Factory Methods /// /// Creates MusicalPause. /// /// Rhythmical order. /// Number of bit from. /// Midi Duration. /// Bar number. /// Returns value. public static MusicalPause CreatePause(byte rhythmicOrder, byte bitFrom, byte duration, int barNumber) { if (duration <= 0) { return null; } var bitRange = new BitRange(rhythmicOrder, bitFrom, duration); var pause = new MusicalPause(bitRange, barNumber); return pause; } #endregion #region Public methods /// Makes a deep copy of the MusicalStrike object. /// Returns object. public override object Clone() { var mt = new MusicalPause(this.BitRange, this.BarNumber); return mt; } /// Makes a deep copy of the MusicalStrike object. /// Returns object. public object CloneTone() { var mt = new MusicalPause(this.BitRange, this.BarNumber); return mt; } #endregion #region Midi Support /// /// Write real tone to midi collection. /// /// Midi event collection. /// Bar division. public void WriteTo(MidiEventCollection midiEvents, int barDivision) { if (midiEvents == null) { return; } //// BitRange br = this.BitRange(this.BarNumber); if (this.RhythmicOrder <= 0) { return; } var duration = MusicalProperties.MidiDuration(this.RhythmicOrder, this.Duration, barDivision); midiEvents.PutNote(0, 0, duration, (byte)MusicalLoudness.None, false, false); //// (byte)0, } /// /// Write Tone Events. /// /// Midi events. /// Bar division. /// Delta Time of bit. /// Delta Time of bar. /// Delta Time Shift. /// Returns value. public bool WriteTo(MidiEventCollection midiEvents, int barDivision, int bitDuration, int barDuration, int deltaTimeShift) { if (midiEvents == null) { return false; } //// BitRange br = this.BitRange(this.BarNumber); if (this.RhythmicOrder <= 0) { return false; } var pause = this; //// MusicalTone melTone = mtone as MusicalTone; var bitRangeTo = pause.BitRange; if (pause.RhythmicOrder <= 0 || bitRangeTo == null) { return false; } var startTime = 1 + (barDuration * (pause.BarNumber - 1)) + (bitDuration * pause.BitFrom) - deltaTimeShift; //// lastTotalTime = 0 var barNumber2 = pause.BarNumberTo != 0 ? pause.BarNumberTo : pause.BarNumber; if (barNumber2 <= 0) { //// 2016/10 return false; } var startTime2 = 1 + (barDuration * (barNumber2 - 1)) + (bitDuration * (bitRangeTo.BitTo + 1)) - deltaTimeShift; if (startTime2 <= startTime) { return false; } //// midiEvent = this.GetNoteOff(deltaTime2 - deltaTimeShift - 1); //// Temporary - decreased by 1, see comment on SortByStartTime var duration = startTime2 - 1; midiEvents.PutNote(0, 0, duration, (byte)MusicalLoudness.None, false, false); //// (byte)0, return true; } #endregion #region String representation /// String representation of the object. /// Returns value. public string ToShortString() { //// virtual var s = new StringBuilder(); s.Append(MusicalStrike.CPause); s.Append(this.Duration); return s.ToString(); } /// String representation of the object. /// Returns value. public override string ToString() { var s = new StringBuilder(string.Empty); s.AppendFormat(CultureInfo.CurrentCulture, "{0,3}", MusicalStrike.CPause); //// for (byte lev = 2; lev <= this.Duration; lev++) { //// s.AppendFormat(CultureInfo.CurrentCulture, "{0,3}", MusicalStrike.CRepeat); } s.AppendFormat(" <{0,3}>", this.Duration); //// s.Append(",lev" + Loudness.ToString(System.Globalization.CultureInfo.CurrentCulture.NumberFormat) + ")"); //// s.Append(base.ToString()); return s.ToString(); } #endregion } }